/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package models;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import play.db.jpa.Model;

/**
 * @author Ousama
 */
@Entity
public class Request extends Model {

    @ManyToOne
    public Organization org;
    @ManyToOne
    public IdeaDeveloper dev;
    @ManyToOne
    public Entities ent;
    @ManyToOne
    public ActionItem item;
    @ManyToOne
    public Topic topic;
    public String type;
    public String status;
    public String body;
    public String inviterName;
    public String title; // for the topic request
    // Type = "JoinOrgFromDevToOrg" || "JoinOrgFromOrgToDev"
    // ||"JoinIdeaDeveloper"||"FriendRequest"
    public long orgId; // for the topic request draft i want to know the org but
    // not to bind it! leave it as is kda
    public String description; // for the topic request bardo since the body is
    // a reserved key word
    public long entId;

    /**
     * request from the organization to Idea Developer or vice versa
     *
     * @param orrg
     *            organization sending or receiving request
     * @param devv
     *            idea developer sending or receiving request
     * @param Type
     *            the type of the request
     * @return the request sent
     */
    public static Request RequestMe(Organization orrg, IdeaDeveloper devv,
            String Type) {
        Request request = new Request();
        request.type = Type;
        request.org = orrg;
        request.dev = devv;
        request.status = "New";
        request.body = "body mo2aktan";
        request.inviterName = "name mo2aktan";
        request.save();
        devv.requests.add(request);
        devv.save();
        orrg.requests.add(request);
        orrg.save();

        Log log = new Log("^ requested ^.");
        log.ids = devv.id + "," + orrg.id;
        log.types = "developer,organization";
        log.save();

        return request;

    }

    // Type = "JoinEntFromDevToEnt" || "JoinEntFromEntToDev"
    // ||"JoinIdeaDeveloper"

    /**
     * request from the entity to Idea Developer or vice versa
     *
     * @param orrg
     *            organization sending or receiving request
     * @param devv
     *            idea developer sending or receiving request
     * @param Type
     *            the type of the request
     * @return the request sent
     */
    public static Request RequestMe(Entities ent, IdeaDeveloper devv,
            String Type) {
        Request request = new Request();
        request.type = Type;
        request.ent = ent;
        request.dev = devv;
        request.status = "New";
        request.body = "body mo2aktan";
        request.inviterName = "name mo2aktan";
        request.save();
        devv.requests.add(request);
        devv.save();
        ent.requests.add(request);
        ent.save();
        ent.liesIn.requests.add(request);
        ent.liesIn.save();
        Log log = new Log("^ requested ^.");
        log.ids = devv.id + "," + ent.id;
        log.types = "developer,entity";
        log.save();

        return request;
    }

    // Type = "JoinItemFromDevToActionItem"
    /**
     * request from the ActionItem to Idea Developer or vice versa
     *
     * @param orrg
     *            ActionItem sending or receiving request
     * @param devv
     *            idea developer sending or receiving request
     * @param Type
     *            the type of the request
     * @return the request sent
     */
    public static Request RequestMe(ActionItem orrg, IdeaDeveloper devv,
            String Type, String body) {
        Request request = new Request();
        request.type = Type;
        request.save();
        request.item = orrg;
        request.save();
        request.dev = devv;
        request.save();
        request.status = "New";
        request.save();
        request.body = body;
        request.save();
        request.inviterName = "name mo2aktan";
        request.save();
        devv.requests.add(request);
        devv.save();
        orrg.requests.add(request);
        orrg.save();

        Log log = new Log("^ requested ^.");
        log.ids = devv.id + "," + orrg.id;
        log.types = "developer,actionitem";
        log.save();

        return request;

    }
    /**
     * @author Ousama
     * @param topic the Topic which is invited to be organizer on it
     * @param dev the developer which is invited
     * @return the request
     */
    public static Request requestMe(Topic topic,IdeaDeveloper dev){
    	Request req = new Request();
    	req.topic = topic;
    	req.type="TopicManager";
    	req.dev=dev;
    	req.status="New";
    	req.save();
    	topic.requests.add(req);
    	topic.save();
    	dev.requests.add(req);
    	dev.save();
    	return req;
    }

    /**
     *
     * a static method that enables an idea developer a to send
     * a topic request when he doesn't find a suitable and it takes the title and body he wishes
     *
     * @author: Dina
     *
     * @param org
     *          organization that the request is sent to
     * @param dev
     *           idea developer sending the request
     * @param title
     *            title of the proposed topic in the request
     * @param description
     *            description of the proposed topic in the request
     * @return
     *        returns the request created
     */
    public static Request RequestMe(Organization org, IdeaDeveloper dev,
            String title, String description) {
        Request request = new Request();
        request.type = "Topic";
        request.org = org;
        org.save();
        request.dev = dev;
        request.status = "Topic";
        request.description = description;
        request.title = title;
        request.save();
        dev.requests.add(request);
        dev.save();
        org.requests.add(request);
        org.save();
        for (int i = 0; i < org.managers.size(); i++) {
            Notification.notify("has requested a topic with title " + title, org.managers.get(i).ideaDeveloper, dev, new Date());
            IdeaDeveloper.sendEMail(org.managers.get(i).ideaDeveloper.eMail, "A New Topic Request", "Dear " + org.managers.get(i).ideaDeveloper.username + ", you have recieved a new topic request in ur managed entity " + org.name + " from " + dev.username + ". Please check it! :)");
        }
        Log log = new Log("^ requested ^.");
        log.ids = dev.id + "," + org.id;
        log.types = "developer,organization";
        log.save();

        return request;

    }

    /**
     *
     * a static method that enables an idea developer a to send
     * a topic request when he doesn't find a suitable and it takes the title and body he wishes
     *
     * @author: Dina
     *
     * @param ent
     *           entity that the request is sent to
     * @param dev
     *           idea developer sending the request
     * @param title
     *            title of the proposed topic in the request
     * @param description
     *            description of the proposed topic in the request
     * @return
     *        returns the request created
     */
    public static Request RequestMe(Entities ent, IdeaDeveloper dev,
            String title, String description) {
        Request request = new Request();
        request.type = "Topic";
        request.ent = ent;
        ent.save();
        request.dev = dev;
        request.status = "Topic";
        request.description = description;
        request.title = title;
        request.save();
        dev.requests.add(request);
        dev.save();
        ent.requests.add(request);
        ent.save();
        for (int i = 0; i < ent.managers.size(); i++) {
            Notification.notify("has requested a topic with title " + title, ent.managers.get(i).ideaDeveloper, dev, new Date());
            IdeaDeveloper.sendEMail(ent.managers.get(i).ideaDeveloper.eMail, "A New Topic Request", "Dear " + ent.managers.get(i).ideaDeveloper.username + ", you have recieved a new topic request in ur managed entity " + ent.name + " from " + dev.username + ". Please check it! :)");
        }
        Log log = new Log("^ requested ^.");
        log.ids = dev.id + "," + ent.id;
        log.types = "developer,entity";
        log.save();

        return request;

    }

    /**
     * Sends a friend request
     *
     * @param inviter
     *            the username of the inviter
     * @param invited
     *            the idea developer being invited
     * @return the request
     */
    public static Request RequestMe(String inviter, IdeaDeveloper invited) {
        Request request = new Request();
        request.type = "FriendRequest";
        request.inviterName = inviter;
        request.dev = invited;
        request.status = "NEW";
        request.description = inviter + " invited yout to be his friend.";
        request.title = "FriendRequest";
        request.save();
        invited.requests.add(request);
        invited.save();

        IdeaDeveloper inviterDev = IdeaDeveloper.find("username=?", inviter).first();
        Log log = new Log("^ asked ^ to be his friend.");
        log.ids = inviterDev.id + "," + invited.id;
        log.types = "developer,ideadeveloper";
        log.save();

        return request;
    }

    /**
     * Initializes the request and adds it to the idea developer requests and to
     * the system to track its status
     *
     * @author OmarKhaled
     * @param entity
     *            the entity which the idea developer is invited
     * @param invitedUser
     *            the user which the invitation is sent to
     * @param Type
     *            represent the direction of the request
     * @return the initialized request
     */
    // public static Request requestToBeOrganizer(Entities entity,
    // IdeaDeveloper invitedUser, String type) {
    // Request newRequest = new Request();
    // newRequest.dev = invitedUser;
    // newRequest.ent = entity;
    // newRequest.type = type;
    // newRequest.status = "New";
    // newRequest.save();
    // invitedUser.requests.add(newRequest);
    // invitedUser.save();
    // entity.requests.add(newRequest);
    // entity.save();
    // return newRequest;
    // }
    /**
     * Saves the decision of an idea developer weather to accept or to reject a
     * request to be an organizer on a specific entity
     *
     * @author KimO
     *
     * @param decision
     *            true to accept and false to reject
     * @param requestID
     *            the request id
     */
    // public static void replyBeOrganizer(Boolean decision, long requestID) {
    // try {
    // Request request = (Request) Request.find("id=?", requestID).first();
    // if (decision) {
    // Organizer newOrganizer = new Organizer();
    // newOrganizer.ideaDeveloper = request.dev;
    // newOrganizer.manages.add(request.ent);
    // newOrganizer.ideaDeveloper.joinedEnt.add(request.ent);
    // newOrganizer.save();
    // request.ent.members.add(request.dev);
    // request.ent.managers.add(newOrganizer);
    // request.dev.save();
    // request.ent.save();
    // request.save();
    // }
    // } catch (Exception e) {
    // // TODO: handle exception
    // }
    // }
    public static void publicOrganizationRequest(Long orgId,
            Long ideaDevoloperId) {

        Organization organization = Organization.findById(orgId);
        IdeaDeveloper devoloper = IdeaDeveloper.findById(ideaDevoloperId);
        if (!organization.members.contains(devoloper)) {

            organization.members.add(devoloper);
            organization.save();
            devoloper.joinedOrg.add(organization);
            devoloper.save();
            for(int i=0; i<organization.managers.size(); i++){
            	Notification.notify(" has joined the organization <a href=\"http://localhost:9000/application/organizationview?name="
                        + organization.name
                        + "\">"
                        + organization.name
                        + "</a>", organization.managers.get(i).ideaDeveloper, devoloper, new Date());
            }
        }

    }

    /**
     * @author Ousama this method for accepting an Request
     * @return the String that results from the action of accepting
     */
    public String Accept() {
        try {
            /** @author Not ousama
             *
             */
            if (type == "FriendRequest") {
                IdeaDeveloper inviter = IdeaDeveloper.find("username=?",
                        inviterName).first();
                // if (dev.friends.contains(inviter)) {
                inviter.friends.add(dev);
                inviter.save();
                dev.friends.add(inviter);
                dev.save();
                // }

            } else {

                if (org != null && dev != null) {
                    if (type.equals("JoinIdeaDeveloper")) {
                        OrganizationLead lead = null;
                        if (OrganizationLead.count("ideaDeveloper = ?", dev) == 0) {
                            lead = OrganizationLead.create(dev);
                        } else {
                            lead = OrganizationLead.find("ideaDeveloper = ?",
                                    dev).first();
                        }
                        org.managers.add(lead);
                        org.save();
                        lead.manages.add(org);
                        lead.save();
                        for(int i = 0 ; i < org.managers.size();i++){
                            Notification.notify("A new Organization Lead is added in organization "+org.name, org.managers.get(i).ideaDeveloper, dev, new Date());
                        }

                    } else {
                        org.members.add(dev);
                        org.save();
                        dev.joinedOrg.add(org);
                        dev.save();
                        for(int i = 0 ; i < org.managers.size();i++){
                            Notification.notify("A new member is added in organization "+org.name, org.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                    }
                } else if (ent != null && dev != null) {
                    if (type.equals("JoinIdeaDeveloper")) {
                        Organizer lead = null;
                        if (Organizer.count("ideaDeveloper = ?", dev) == 0) {
                            lead = Organizer.create(dev);
                        } else {
                            lead = Organizer.find("ideaDeveloper = ?", dev).first();
                        }
                        ent.managers.add(lead);
                        ent.save();
                        lead.manages.add(ent);
                        lead.save();
                        for(int i = 0 ; i < ent.liesIn.managers.size();i++){
                            Notification.notify("A new Organizer is added in Entity "+ent.name+" in organization "+ent.liesIn.name, ent.liesIn.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                        for(int i = 0 ; i < ent.managers.size();i++){
                            Notification.notify("A new Organizer is added in Entity "+ent.name+" in organization "+ent.liesIn.name, ent.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                    } else {
                        ent.members.add(dev);
                        ent.save();
                        dev.joinedEnt.add(ent);
                        dev.save();
                        for(int i = 0 ; i < ent.liesIn.managers.size();i++){
                            Notification.notify("A new member is added in Entity "+ent.name+" in organization "+ent.liesIn.name, ent.liesIn.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                        for(int i = 0 ; i < ent.managers.size();i++){
                            Notification.notify("A new member is added in Entity "+ent.name+" in organization "+ent.liesIn.name, ent.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                    }
                } else if (item != null && dev != null) {
                    item.volunteers.add(dev);
                    item.save();
                    dev.actionItem.add(item);
                    dev.save();
                    for(int i = 0 ; i < item.managers.size();i++){
                            Notification.notify("A new volunteer on ActionItem "+item.title, item.managers.get(i).ideaDeveloper, dev, new Date());
                        }
                } else if (topic != null && dev!=null){
                	Organizer orgz = Organizer.find("ideaDeveloper = ?", dev).first();
                	if(orgz == null){
                		orgz = Organizer.create(dev);
                		orgz.save();
                	}
                	topic.managers.add(orgz);
                	topic.save();
                	orgz.managedTopics.add(topic);
                	orgz.save();
                }
            }
            status = "ACCEPTED";
            this.save();
            Log log = new Log("Request  ^ Accepted"); // the body of the log
            // entry
            log.ids = this.id + ""; // the ids separated by , NO SPACES
            log.types = "request"; // the types separated by , NO SPACES
            log.save(); // saving the log entry
            return "DONE";
        } catch (Exception exp) {
            return "ERROR OCCURED";
        }
    }
    /**
     * @author Ousama
     * @return the status that it is done
     */
    public String Decline(){
         Log log = new Log("Request  ^ Deleted"); // the body of the log
            // entry
            log.ids = this.id + ""; // the ids separated by , NO SPACES
            log.types = "request"; // the types separated by , NO SPACES
            log.save(); // saving the log entry
            this.delete2();
        return "Done";
    }

    public static void replyRequest(long requestId, Boolean decision) {
        Request requestToReplyOn = ((Request) Request.find("id=?", requestId).first());
        if (decision) {
            requestToReplyOn.Accept();
        } else {
            requestToReplyOn.status = "REJECTED";
            requestToReplyOn.save();
        }
    }

    /**
     * deletes the request and all its components
     */
    public void delete2() {
        // removes it from the sources
        if (org != null) {
            org.requests.remove(this);
            org.save();
        }
        if (dev != null) {
            dev.requests.remove(this);
            dev.save();
        }

        if (ent != null) {
            ent.requests.remove(this);
            ent.save();
        }

        if (item != null) {
            item.requests.remove(this);
            item.save();
        }
        Log log = new Log("^ is deleted.");
        log.ids = this.id + "";
        log.types = "request";
        log.save();
        this.delete();

       
    }

    /**
     *
     * @param title
     *            title of the proposed topic in the request
     * @param description
     *            description of the proposed topic
     * @param dev
     *            idea developer drafting the request
     * @param orgId
     *            the id of the organization he's drafting his request to
     * @return
     */
    public static Request draftMeOrg(String title, String description,
            IdeaDeveloper dev, long orgId) {
        Request request = new Request();
        request.title = title;
        request.type = "TopicDraft";
        request.orgId = orgId;
        // org.save();
        request.dev = dev;
        request.status = "TopicDraft";
        request.description = description;
        request.save();
        dev.requests.add(request);
        dev.save();

        Log log = new Log("^ requested a draft topic from ^.");
        log.ids = dev.id + "," + orgId;
        log.types = "developer,organization";
        log.save();

        return request;
    }

    /**
     *
     * @param title
     *            title of the proposed topic in the request
     * @param description
     *            description of the proposed topic
     * @param dev
     *            idea developer drafting the request
     * @param entId
     *            the id of the entity he's drafting his request to
     * @return
     */
    public static Request draftMeEnt(String title, String description,
            IdeaDeveloper dev, long entId) {
        Request request = new Request();
        request.title = title;
        request.type = "TopicDraft";
        request.entId = entId;
        // org.save();
        request.dev = dev;
        request.status = "TopicDraft";
        request.description = description;
        request.save();
        dev.requests.add(request);
        dev.save();

        Log log = new Log("^ requested a draft topic from ^.");
        log.ids = dev.id + "," + entId;
        log.types = "developer,entity";
        log.save();
        return request;
    }

    /**
     * this method changes the status of a volunteer request to rejected
     *
     * @author Amr Gamal
     * @param requestId
     *            this is the Id of the request to be rejected
     */
    public static void reject(long requestId) {
        Request requestToReplyOn = ((Request) Request.find("id=?", requestId).first());
        requestToReplyOn.status = "REJECTED";
        requestToReplyOn.save();
    }

    /**
     * This method is given a list of request and returns a list of requests
     * whose statuses are "PENDING"
     *
     * @author Amr Gamal
     * @param req
     *            this is a list of requests
     * @return List<Request> this method returns a list of requests whose status
     *         are "PENDING"
     */
    public static List<Request> getPendingRequests(List<Request> req) {
        List<Request> requests = new ArrayList<Request>();
        for (int i = 0; i < req.size(); i++) {
            if (req.get(i).status.equals("PENDING")) {
                requests.add(req.get(i));
            }
        }
        return requests;
    }

    /**
     * this method adds is invoked when the Volunteer request is accepted, it
     * adds the action item volunteered on to list of action items that the idea
     * developer volunteers on. Besides it adds the volunteering IdeaDeveloper
     * to the list of volunteering idea developers on the action item
     */
    public void accept2() {
        item.requests.remove(this);
        item.save();
        dev.requests.remove(this);
        dev.save();
        item.volunteers.add(dev);
        item.save();
        dev.actionItem.add(item);
        dev.save();
    }
}
